from .models import ProviderLocation, ProviderServices, ProviderTelehealth, BillingAddress, BillingInfo, \
    TrackingDeviceLogin
from .telehealths import get_telehealth_token
from apps.users.views import *

@api_view(('GET', 'POST'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_location_api(request):
    if request.method == 'POST':
        data = request.data
        is_default = data.get('is_default', False)
        if is_default is True:
            ProviderLocation.objects.all().update(is_default=False)
        ProviderLocation.objects.create(**data)

        return Response({"msg": "Provider's Location has been created"}, status=status.HTTP_201_CREATED)

    if request.method == 'GET':
        ordering = request.GET.get('ordering', '-created_at')
        locations = ProviderLocation.objects.all().order_by(ordering).values(
            *['id', 'name', 'address', 'state', 'city', 'zipcode', 'icon', 'place_of_service', 'is_default'])
        provider_locations = list(locations)

        return paginated_queryset_response(queryset=provider_locations, request=request)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_location_id_api(request, locations_id):
    location = get_object_or_404(ProviderLocation, id=locations_id)
    if request.method == 'GET':
        provider_location = model_to_dict(location,
                                          exclude=['created_at', 'updated_at'])

        return Response(provider_location, status=status.HTTP_200_OK)

    if request.method == 'DELETE':
        location.delete()
        return Response({"msg": "Provider's Location has been deleted"}, status=status.HTTP_204_NO_CONTENT)

    if request.method == 'PATCH':
        data = request.data
        is_default = data.get('is_default', False)
        if is_default is True:
            ProviderLocation.objects.all().update(is_default=False)

        for field_name, field_value in data.items():
            if hasattr(ProviderLocation, field_name):
                setattr(location, field_name, field_value)

        location.save()

        return Response({"msg": "Provider's Location has been updated"}, status=status.HTTP_200_OK)


@api_view(('GET', 'POST'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_service_api(request):
    if request.method == 'POST':
        data = request.data
        ProviderServices.objects.create(**data)

        return Response({"msg": "Provider's Service has been created"}, status=status.HTTP_201_CREATED)

    if request.method == 'GET':
        ordering = request.GET.get('ordering', '-created_at')
        services = ProviderServices.objects.all().order_by(ordering).values(
            *['id', 'code', 'service', 'time', 'fee'])
        provider_services = list(services)
        return paginated_queryset_response(queryset=provider_services, request=request)

@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_service_id_api(request, service_id):
    service = get_object_or_404(ProviderServices, id=service_id)
    if request.method == 'GET':
        provider_service = model_to_dict(service,
                                         exclude=['created_at', 'updated_at'])

        return Response(provider_service, status=status.HTTP_200_OK)

    if request.method == 'DELETE':
        service.delete()
        return Response({"msg": "Provider's Service has been deleted"}, status=status.HTTP_204_NO_CONTENT)

    if request.method == 'PATCH':
        data = request.data

        for field_name, field_value in data.items():
            if hasattr(ProviderServices, field_name):
                setattr(service, field_name, field_value)

        service.save()

        return Response({"msg": "Provider's Service has been updated"}, status=status.HTTP_200_OK)


@api_view(('GET', 'POST'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_telehealth_api(request):
    if request.method == 'POST':
        data = request.data
        data['access_token'], data['refresh_token'] = get_telehealth_token(data)
        ProviderTelehealth.objects.create(**data)

        return Response({"msg": "Provider's Telehealth has been created"}, status=status.HTTP_201_CREATED)

    if request.method == 'GET':

        ordering = request.GET.get('ordering', '-created_at')
        telehealth = ProviderTelehealth.objects.all().order_by(ordering).values(
            *['telehealth_type', 'access_token', 'refresh_token'])
        provider_telhealths = list(telehealth)
        return paginated_queryset_response(queryset=provider_telhealths, request=request)



@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_telehealth_id_api(request, telehealth_id):
    telehealths = get_object_or_404(ProviderTelehealth, id=telehealth_id)
    if request.method == 'GET':
        provider_telehealth = model_to_dict(telehealths,
                                            exclude=['created_at', 'updated_at'])

        return Response(provider_telehealth, status=status.HTTP_200_OK)

    if request.method == 'DELETE':
        telehealths.delete()
        return Response({"msg": "Provider's Telehealth has been deleted"}, status=status.HTTP_204_NO_CONTENT)

    if request.method == 'PATCH':
        data = request.data

        for field_name, field_value in data.items():
            if hasattr(ProviderTelehealth, field_name):
                setattr(telehealths, field_name, field_value)

        telehealths.save()

        return Response({"msg": "Provider's Telehealth has been updated"}, status=status.HTTP_200_OK)


@api_view(('GET', 'POST', 'PATCH'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_calendar_id_api(request):
    calendar = Calendar.objects.filter().first()
    if request.method == 'GET':
        if calendar:
            provider_calendar = model_to_dict(calendar,
                                          exclude=['created_at', 'updated_at'])
            return Response(provider_calendar, status=status.HTTP_200_OK)
        else:
            return Response({'msg': 'Not Found'}, status=status.HTTP_404_NOT_FOUND)

    if request.method == 'PATCH':
        data = request.data

        for field_name, field_value in data.items():
            if hasattr(Calendar, field_name):
                setattr(calendar, field_name, field_value)

        calendar.save()
        provider_calendar = model_to_dict(calendar,
                                          exclude=['created_at', 'updated_at'])
        return Response(provider_calendar, status=status.HTTP_200_OK)

    if request.method =='POST':
        Calendar.objects.create( start_time="06:00", end_time="23:00")
        return Response(status=status.HTTP_201_CREATED)


@api_view(('GET', 'POST'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_billing_address_api(request):
    if request.method == 'POST':
        data = request.data
        BillingAddress.objects.create(**data)

        return Response({"msg": "Provider's Billing Address has been created"}, status=status.HTTP_201_CREATED)

    if request.method == 'GET':
        ordering = request.GET.get('ordering', '-created_at')
        addresses = BillingAddress.objects.all().order_by(ordering)
        provider_addresses = list()
        for query in addresses:
            provider_addresse = model_to_dict(query,
                                              exclude=['created_at', 'updated_at'])
            provider_addresses.append(provider_addresse)
        return paginated_queryset_response(queryset=provider_addresses, request=request)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_billing_address_id_api(request, address_id):
    billing_address = get_object_or_404(BillingAddress, id=address_id)
    if request.method == 'GET':
        billing_address = model_to_dict(billing_address,
                                        exclude=['created_at', 'updated_at'])

        return Response(billing_address, status=status.HTTP_200_OK)

    if request.method == 'DELETE':
        billing_address.delete()
        return Response({"msg": "Provider's Billing Address has been deleted"}, status=status.HTTP_204_NO_CONTENT)

    if request.method == 'PATCH':

        billing_address = request.data.get('name', billing_address.name)
        billing_address = request.data.get('address', billing_address.address)
        billing_address.save()

        # for field_name, field_value in data.items():
        #     if hasattr(BillingAddress, field_name):
        #         setattr(billing_address, field_name, field_value)

        billing_address.save()

        return Response({"msg": "Provider's Billing Address has been updated"}, status=status.HTTP_200_OK)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_invoice_setting_id_api(request, invoice_setting_id):
    with schema_context(request.user.provider.schema_name):
        invoice_setting = InvoiceSetting.objects.filter().first()
    if request.method == 'GET':
        if invoice_setting:
            billing_address = model_to_dict(invoice_setting,
                                            exclude=['created_at', 'updated_at'])
            get_assigned_url = billing_address['logo_image'].url if billing_address['logo_image'] else ''
            if get_assigned_url:
                billing_address['logo_image'] = get_assigned_url
            else:
                billing_address['logo_image'] = ""
            return Response(billing_address, status=status.HTTP_200_OK)
        else:
            return Response({}, status=status.HTTP_200_OK)

    if request.method == 'PATCH':
        data = request.data.dict()
        if 'include_logo' in data.keys():
            invoice_setting.include_logo = eval(data['include_logo'].capitalize())

        invoice_setting.footer_information = data.get('footer_information', invoice_setting.footer_information)
        invoice_setting.logo_image = data.get('logo_image', invoice_setting.logo_image)
        invoice_setting.subject = data.get('subject', invoice_setting.subject)
        invoice_setting.message = data.get('message', invoice_setting.message)

        invoice_setting.save()
        billing_address = model_to_dict(invoice_setting,
                                        exclude=['created_at', 'updated_at'])
        get_assigned_url = gcs_operations.generate_assigned_url(
            billing_address['logo_image'].url if billing_address['logo_image'] else '')
        if get_assigned_url:
            billing_address['logo_image'] = get_assigned_url
        else:
            billing_address['logo_image'] = ""
        return Response(billing_address, status=status.HTTP_200_OK)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_super_bill_invoice_setting_id_api(request, invoice_setting_id=None):
    try:
        with schema_context(request.user.provider.schema_name):
            super_bill_invoice_setting = SuperBillSetting.objects.filter().first()
        if request.method == 'GET':
            if super_bill_invoice_setting:
                billing_address = model_to_dict(super_bill_invoice_setting,
                                                exclude=['created_at', 'updated_at'])
                get_assigned_url = gcs_operations.generate_assigned_url(
                    billing_address['logo_image'].url if billing_address['logo_image'] else '')
                if get_assigned_url:
                    billing_address['logo_image'] = get_assigned_url
                else:
                    billing_address['logo_image'] = ""
                return Response(billing_address, status=status.HTTP_200_OK)
            else:
                return Response({}, status=status.HTTP_200_OK)

        if request.method == 'PATCH':
            data = request.data.dict()

            if 'include_logo' in data.keys():
                super_bill_invoice_setting.include_logo = eval(data['include_logo'].capitalize())
            if 'include_diagnosis_description' in data.keys():
                super_bill_invoice_setting.include_diagnosis_description = eval(
                    data['include_diagnosis_description'].capitalize())
            if 'include_signature_line' in data.keys():
                super_bill_invoice_setting.include_signature_line = eval(
                    data['include_signature_line'].capitalize())

            super_bill_invoice_setting.logo_image = data.get('logo_image', super_bill_invoice_setting.logo_image)
            super_bill_invoice_setting.footer_information = data.get('footer_information', super_bill_invoice_setting.footer_information)
            super_bill_invoice_setting.subject = data.get('subject', super_bill_invoice_setting.subject)
            super_bill_invoice_setting.message = data.get('message', super_bill_invoice_setting.message)

            super_bill_invoice_setting.save()
            billing_address = model_to_dict(super_bill_invoice_setting,
                                            exclude=['created_at', 'updated_at'])
            get_assigned_url = gcs_operations.generate_assigned_url(
                billing_address['logo_image'].url if billing_address['logo_image'] else '')
            if get_assigned_url:
                billing_address['logo_image'] = get_assigned_url
            else:
                billing_address['logo_image'] = ""
            return Response(billing_address, status=status.HTTP_200_OK)
    except Exception as e:
        return Response({
            'success': False, 'message': f'Failed to get super bill invoice setting because of {str(e)}'
        }, status=status.HTTP_400_BAD_REQUEST)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_super_bill_setting_id_api(request, super_bill_id):
    super_bill_setting = get_object_or_404(SuperBillSetting, id=super_bill_id)
    if request.method == 'GET':
        super_bill_setting = model_to_dict(super_bill_setting,
                                           exclude=['created_at', 'updated_at'])

        return Response(super_bill_setting, status=status.HTTP_200_OK)

    if request.method == 'PATCH':
        data = request.data

        for field_name, field_value in data.items():
            if hasattr(InvoiceSetting, field_name):
                setattr(super_bill_setting, field_name, field_value)

        super_bill_setting.save()

        return Response({"msg": "Provider's Super Billing Setting has been updated"}, status=status.HTTP_200_OK)


@api_view(['DELETE'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAdminUser | IsProvider])
@transaction.atomic
def super_bill_image_delete_api(request, super_bill_id):
    try:
        super_bill_setting = SuperBillSetting.objects.filter().first()
        if not super_bill_setting:
            return Response({
                'success': False,
                'message': f'Failed to upload image because location does not exist'
            }, status=status.HTTP_400_BAD_REQUEST)
        if super_bill_setting.logo_image:
            delete_file(super_bill_setting.logo_image.name)
        super_bill_setting.logo_image = None
        super_bill_setting.save()
        return Response(
            {'msg': 'Image has been deleted'},
            status=status.HTTP_200_OK
        )
    except Exception as e:
        return Response({
            'success': False,
            'message': f'Failed to upload image because of {str(e)}'
        }, status=status.HTTP_400_BAD_REQUEST)


@api_view(['DELETE'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAdminUser | IsProvider])
@transaction.atomic
def invoice_setting_image_delete_api(request, invoice_setting_id):
    try:
        invoice_setting = InvoiceSetting.objects.filter().first()
        if not invoice_setting:
            return Response({
                'success': False,
                'message': f'Failed to upload image because location does not exist'
            }, status=status.HTTP_400_BAD_REQUEST)
        if invoice_setting.logo_image:
            delete_file(invoice_setting.logo_image.name)
        invoice_setting.logo_image = None
        invoice_setting.save()
        return Response(
            {'msg': 'Image has been deleted'},
            status=status.HTTP_200_OK
        )
    except Exception as e:
        return Response({
            'success': False,
            'message': f'Failed to upload image because of {str(e)}'
        }, status=status.HTTP_400_BAD_REQUEST)

@api_view(('GET', 'POST'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_billing_info_api(request):
    if request.method == 'POST':
        data = request.data
        BillingInfo.objects.all().delete()
        billing_info = BillingInfo.objects.create(**data)

        billing_info = model_to_dict(billing_info,
                                     exclude=['created_at', 'updated_at'])

        return Response(billing_info, status=status.HTTP_201_CREATED)

    if request.method == 'GET':
        ordering = request.GET.get('ordering', '-created_at')
        billing_information = BillingInfo.objects.all().order_by(ordering)
        billing_infos = list()
        for query in billing_information:
            billing_info = model_to_dict(query,
                                         exclude=['created_at', 'updated_at'])
            billing_infos.append(billing_info)
        return paginated_queryset_response(queryset=billing_infos, request=request)


@api_view(('GET', 'PATCH', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def providers_billing_info_id_api(request, billing_info_id=None):
    # billing_info = get_object_or_404(BillingInfo, id=billing_info_id)
    billing_info = BillingInfo.objects.first()
    if request.method == 'GET':
        if billing_info:
            billing_info = model_to_dict(billing_info,
                                     exclude=['created_at', 'updated_at'])

            return Response(billing_info, status=status.HTTP_200_OK)
        else:
            return Response({'msg': 'Info not found'}, status=status.HTTP_404_NOT_FOUND)

    if request.method == 'DELETE':
        billing_info.delete()
        return Response({"msg": "Provider's Billing Info has been deleted"}, status=status.HTTP_204_NO_CONTENT)

    if request.method == 'PATCH':
        data = request.data

        for field_name, field_value in data.items():
            if hasattr(BillingInfo, field_name):
                setattr(billing_info, field_name, field_value)

        billing_info.save()

        return Response({"msg": "Provider's Billing Info has been updated"}, status=status.HTTP_200_OK)


@api_view(('GET', 'POST', 'DELETE'))
@authentication_classes([JWTAuthentication])
@permission_classes([IsProvider])
@transaction.atomic
def tracking_device_login_api(request):
    if request.method == 'POST':
        # TrackingDeviceLogin.objects.filter().delete()
        device_id = request.data.get('device_id', None)
        if device_id:
            device = TrackingDeviceLogin.objects.filter(device_id=device_id).exists()
            if device:
                return Response({'msg': 'Device Already Exist'}, status=status.HTTP_200_OK)
            TrackingDeviceLogin.objects.create(device_id=device_id)
            return Response({'msg': 'Device Login Created'}, status=status.HTTP_200_OK)
        return Response({'msg': 'Device id is required to complete your request'}, status=status.HTTP_200_OK)

    if request.method == 'GET':
        tracking = TrackingDeviceLogin.objects.filter().first()
        if tracking:
            return Response({'device_id': tracking.device_id, 'created_at': tracking.created_at, 'updated_at': tracking.updated_at}, status=status.HTTP_200_OK)
        return Response({'msg': 'There is no Id set for this provider'})